package ij.umasuo.algorithms.gaussian;

import ij.IJ;
import ij.measure.ResultsTable;
import ij.plugin.filter.Analyzer;
import ij.umasuo.MyConstants;
import ij.umasuo.algorithms.natives.NativeProcessor;
import ij.umasuo.gui.working.ReconstructionViewer;

import java.text.DecimalFormat;

public class GaussianProcessor {
	
	private NativeProcessor prossor;
	public static ResultsTable ptable = Analyzer.getResultsTable(); // Particle table
	public int curCount = 0;//current point count
	private int imageCount = 0;
	
	private DecimalFormat dcmFmt = new DecimalFormat("0.00000");
	public GaussianProcessor(){
		prossor = new NativeProcessor();
		ptable.setPrecision(3);
		
	}
	public void init(){
		ptable = Analyzer.getResultsTable(); // Particle table
		 curCount = 0;//current point count
		 int imageCount = 0;
	}
	
	public void process(int d,String path,int channel,int frame) {
		
		//this is just for single thread
		String tmpResult = "";
		try{
			tmpResult = prossor.process(d,path,MyConstants.PSF,MyConstants.PFA,MyConstants.PW);
		}catch(Exception e){
			IJ.error("dll error", e.getMessage());
		}
		
	
		imageCount ++;
		curCount = ptable.getCounter();
		if(MyConstants.IS_3D){
			add3DValue(tmpResult,channel,frame);
		}else{
			add2DValue(tmpResult,channel,frame);
		}
//		IJ.log("gaussian:" + ptable.getCounter());
		ReconstructionViewer.getInstance().update();
		//show current state
		IJ.showStatus((ptable.getCounter() - curCount) + " part/frame, detected " + curCount + " particles" + "  ImageCount:" + imageCount);
	}
	
	public void showResult(){
		//TODO here we show the result table we got

		if (ptable.getCounter() < 5000000) {//show the results
			IJ.showStatus("Creating particle table, this should take a few seconds...");
			ptable.show("Results");
		} else
			IJ.showMessage("Warning","Results table has too many particles, they will not be shown but the data still exists within it\nyou can still use all the plugin functionality or save table changes though the 'Save Particle Table' command.");

	}
	
	public void add2DValue(String result,int color,int frame){
		if(result==null||result.equals("")){
			return;
		}
		String[] tmpResult1 = result.split("\n");
		for(int i =0;i<tmpResult1.length;i++){
			//TODO here we add the result to the table
			String[] tmpResult2 = tmpResult1[i].split("\t");
			synchronized(ptable){
				ptable.incrementCounter();
				ptable.addValue("Intensity", Double.parseDouble(tmpResult2[0]));
				ptable.addValue("X (px)",  Double.parseDouble(dcmFmt .format( Double.parseDouble(tmpResult2[1]))));
				ptable.addValue("Y (px)",  Double.parseDouble(dcmFmt .format(  Double.parseDouble(tmpResult2[2]))));
				ptable.addValue("X (nm)", Double.parseDouble(dcmFmt .format( Double.parseDouble(tmpResult2[1]) * 80)));//TODO why is 80??
				ptable.addValue("Y (nm)", Double.parseDouble(dcmFmt .format( Double.parseDouble(tmpResult2[2]) * 80)));
				ptable.addValue("Z (nm)", 0);
				ptable.addValue("Left-Width (px)", 0);
				ptable.addValue("Right-Width (px)", 0);
				ptable.addValue("Up-Height (px)", 0);
				ptable.addValue("Down-Height (px)", 0);
				ptable.addValue("X Symmetry (%)", 0);
				ptable.addValue("Y Symmetry (%)", 0);
				ptable.addValue("Width minus Height (px)", 0);
				ptable.addValue("Frame Number", frame);
		        ptable.addValue("Color", color);
				ptable.addValue("Photon Count", 0);
//				System.out.println(ptable.getValue("X (nm)", 0));
			}
		}
	}
	public void add3DValue(String result,int color,int frame){
		if(result==null||result.equals("")){
			return;
		}
		String[] tmpResult1 = result.split("\n");
		for(int i =0;i<tmpResult1.length;i++){
			//TODO here we add the result to the table
			String[] tmpResult2 = tmpResult1[i].split("\t");
			try{
				synchronized(ptable){
					ptable.incrementCounter();
					ptable.addValue("Intensity", Double.parseDouble(tmpResult2[0]));
					ptable.addValue("X (px)",  Double.parseDouble(dcmFmt .format( Double.parseDouble(tmpResult2[1]))));
					ptable.addValue("Y (px)",  Double.parseDouble(dcmFmt .format( Double.parseDouble(tmpResult2[2]))));
					ptable.addValue("X (nm)", Double.parseDouble(dcmFmt .format( Double.parseDouble(tmpResult2[1]) * 80)));
					ptable.addValue("Y (nm)", Double.parseDouble(dcmFmt .format( Double.parseDouble(tmpResult2[2]) * 80)));
					ptable.addValue("Z (nm)", Double.parseDouble(tmpResult2[3]));
					ptable.addValue("Left-Width (px)", Double.parseDouble(tmpResult2[4]));
					ptable.addValue("Right-Width (px)", Double.parseDouble(tmpResult2[4]));
					ptable.addValue("Up-Height (px)", Double.parseDouble(tmpResult2[5]));
					ptable.addValue("Down-Height (px)", Double.parseDouble(tmpResult2[5]));
					ptable.addValue("X Symmetry (%)", 0);
					ptable.addValue("Y Symmetry (%)", 0);
					ptable.addValue("Width minus Height (px)", 0);
					ptable.addValue("Frame Number", frame);
			        ptable.addValue("Color", color);
					ptable.addValue("Photon Count", 0);
					
				}
			}catch(Exception e){
				ptable.deleteRow(ptable.getCounter() - 1);
			}
		}
	}

}

class ProcessorThread extends Thread{
	private NativeProcessor prossor;
	private String path = null;
	public ProcessorThread(NativeProcessor prossor,String path){
		this.path = path;
		this.prossor = prossor;
	}
	@Override
	public void run() {
		String tmpResult= prossor.process(2,path,1.671,40,160);
		String [] results  = tmpResult.split("\t");
		//TODO here we add the result to the table
		synchronized(GaussianProcessor.ptable){
			GaussianProcessor.ptable.incrementCounter();
			GaussianProcessor.ptable.addValue("Intensity", results[0]);
			GaussianProcessor.ptable.addValue("X (px)",  results[2]);
			GaussianProcessor.ptable.addValue("Y (px)",  results[3]);
			GaussianProcessor.ptable.addValue("X (nm)", 0);
			GaussianProcessor.ptable.addValue("Y (nm)", 0);
			GaussianProcessor.ptable.addValue("Z (nm)", 0);
			GaussianProcessor.ptable.addValue("Left-Width (px)", 0);
			GaussianProcessor.ptable.addValue("Right-Width (px)", 0);
			GaussianProcessor.ptable.addValue("Up-Height (px)", 0);
			GaussianProcessor.ptable.addValue("Down-Height (px)", 0);
			GaussianProcessor.ptable.addValue("X Symmetry (%)", 0);
			GaussianProcessor.ptable.addValue("Y Symmetry (%)", 0);
			GaussianProcessor.ptable.addValue("Width minus Height (px)", 0);
			GaussianProcessor.ptable.addValue("Frame Number", 0);
			GaussianProcessor.ptable.addValue("Color", 0);
			GaussianProcessor.ptable.addValue("Photon Count", 0);
		}
	}
	
}
